<?php

class TestDbMapperTool extends UnitTestCase {

    function setUp() {
        $kit=&Webappkit::getkit('webappkit.db');
        $this->a_items=&$kit->a_items;
        $this->b_items=&$kit->b_items;
    }

    /**
     * here we create an object with undefined key
     * save it into database and obtain the defined key
     * get the object by its key
     * delete the object by its key
     */
    function testSimpleObjectSequence() {
        $a_items=$this->a_items;
        // create an object with undefined key
        $item=new MockDbItem_A('Some Text');
        // inserting
        if (!$this->assertTrue($a_items->save($item)
            ,"save() should return true"))
            return false;
        $id=$item->id;
        $this->assertNotNull($id,"save() should set key member %s");
        $this->assertTrue($a_items->has($id)
            ,"has($id) should return true");
        // $this->dump($item);
        $bad=new MockDbItem_A(null);
        if (!$this->assertFalse($a_items->save($bad)
            ,'save() should return false if insertion is rejected')) {
            $this->fail($this->mapper->sqlerror());
        }
        // getting a copy
        $copy=$a_items->get($id);
        $this->assertEqual($item,$copy
            ,"should got a copy of previously inserted object %s");
        // updating
        $new_text='Text has been updated.';
        $item->text=$new_text;
        $this->assertTrue(
            $a_items->save($item),"save() should return true");
        // getting copy and checking
        $copy=$a_items->get($id);
        $this->assertEqual($copy->text,$new_text,"save() should update... %s");

        // deleting
        $this->assertTrue($a_items->delete($id)
            ,"delete($id) should return true");
        $this->assertFalse(
            $a_items->has($id)
            ,"object MockDbItem_A with id $id should have been deleted");
        // checking that other objects have not been affected
    }

    /**
     * here we test using complex objects involving table associations
     */
    function testAssociationSequence() {
        $a_items=$this->a_items;
        $b_items=$this->b_items;
        // building a complex item
        $a1=$a_items->get(1);
        $a2=$a_items->get(2);
        $a3=$a_items->get(3);
        if (!$this->assertIsA($a1,'MockDbItem_A')
        or !$this->assertIsA($a2,'MockDbItem_A')) {
            return false;
        }
        $b=new MockDbItem_B($a1,array($a1,$a2));
        // first saving
        $this->assertTrue($b_items->save($b));
        $id=$b->id;
        $copy=$b_items->get($id);
        if (!$this->assertEqual($b,$copy)) {
            $this->dump($copy);
        }
        // updating
        $b->collection=array($a2,$a3);
        if (!$b_items->save($b)) {
            $this->fail($b_items->sqlError());
        }
        $copy=$b_items->get($id);
        if (!$this->assertEqual($b,$copy)) {
            $this->dump($copy);
        }
        // deleting
        $this->assertTrue($b_items->delete($id),"delete($id) should return true");
        // saving another object with same id to check that associations have been removed
        $b2=new MockDbItem_B($a2,array(),$id);
        // $this->dump($b2);
        if (!$b_items->save($b2)) {
            $this->fail("could not save with same id $id");
            return false;
        }
        $copy=$b_items->get($id);
        $this->assertEqual($b2,$copy,"replaced object shall not inherit previous associations");
    }/**/
}

/**
 * a very simple, atomic class
 */
class MockDbItem_A {
    function MockDbItem_A($text=null,$id=null) {
        $this->text=$text;
        if ($id)
            $this->id=$id;
    }

    /**
     * @var int database key
     */
    var $id;

    /**
     * @var string
     */
    var $text;

    function __toString() {
        return $this->text;
    }
}

/**
 * a more complex class having other db objects as member
 * therefore involving simple associations
 */
class MockDbItem_B {
    function MockDbItem_B($desc=null,$collection=array(),$id=null) {
        $this->desc=$desc;
        $this->collection=$collection;
        if ($id)
            $this->id=$id;
    }
    /**
     * @var int database key
     */
    var $id;

    /**
     * @var MockDbItem_A a one-to-many realtionship
     */
    var $desc;

    /**
     * @var array MockDbItem_A / a many-to-many assoc
     */
    var $collection=array();
}
